﻿using System;
using System.Collections.Generic ;
using System.Data ;
using System.Linq;
using System.Text;
using LayerData.DataBaseManager;
using LayerEntity.Persona;
using LayerEntity.Persona.RecursosHumanos ;
using LayerEntity.Sistema;
using Npgsql;

namespace LayerData.Persona
{
    public class MantenimientoPersona
    {
        #region Variables
        readonly string mensajeExecuteReader = "Error al Recuperar #replace, revise lo Siguiente: ";
        readonly IPostgreSqlConnectionInfo pCon;
        public IPostgreSqlConnectionInfo CurrentConection { get; set; }
        #endregion

        #region Constructores
        public MantenimientoPersona(IPostgreSqlConnectionInfo con)
        {
            this.pCon = con;
            this.CurrentConection = con;
        }

        public MantenimientoPersona()
        {
            this.pCon = ObjectFactory.CreateConnectionInfo();
        }

        #endregion

        #region Funciones Privadas

        /// <summary>
        /// Funciones que genera la query para personas
        /// </summary>
        /// <param name="per">Tipo de persona a buscar</param>
        /// <param name="limit">El numero de filas a seleccionar</param>
        /// <returns></returns>
        private string GetQueryPersona(EnumTipoPersona per, int limit, string andCondicion)
        {
            StringBuilder query = new StringBuilder();
            query.Append("select * from planillas.tb_persona  a ");
            query.AppendFormat("where substring(a.tipo_per_sistema,{0},1)='1' ", ((int)per).ToString());
            query.AppendFormat(" {0}", andCondicion);
            query.Append(" order by a.id_persona desc ");
            if (limit > 0)
            {
                query.AppendFormat(" limit {0} ;", limit.ToString());
            }
            else
            {
                query.Append(";");
            }
            return query.ToString();
        }

        /// <summary>
        /// Genera una query para seleccionar las direcciones de acuerdo al tipo de direccion
        /// </summary>
        /// <param name="per">
        /// Tipo de persona a buscar
        /// </param>
        /// <returns></returns>
        private string GetQueryDireccion(EnumTipoPersona per)
        {
            StringBuilder query = new StringBuilder();
            query.Append("select * from planillas.v_persona_direccion  a ");
            query.AppendFormat("where substring(a.tipo_per_sistema,{0},1)='1' ", ((int)per).ToString());
            query.Append("order by a.id_persona desc; ");
            return query.ToString();        
        }

        private string GetQueryCuentasCorrientes(EnumTipoPersona per)
        {
            StringBuilder query = new StringBuilder();
            query.Append("select * from planillas.v_persona_cuenta_corriente  a ");
            query.AppendFormat("where substring(a.tipo_per_sistema,{0},1)='1' ", ((int)per).ToString());
            query.Append("order by a.id_persona desc; ");
            return query.ToString();
        }

        private string GetQueryContactos(EnumTipoPersona per)
        {
            StringBuilder query = new StringBuilder();
            query.Append("select * from planillas.v_persona_contactos  a ");
            query.AppendFormat("where substring(a.tipo_per_sistema,{0},1)='1' ", ((int)per).ToString());
            query.Append("order by a.id_persona desc; ");
            return query.ToString();
        }

        private List<EDireccion> GetAddress(EnumTipoPersona per)
        {
            NpgsqlDataReader dr = null;
            List<EDireccion> direcciones = new List<EDireccion>();
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryDireccion(per));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            direcciones.Add(new EDireccion(dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Clientes"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            return direcciones;
        }

        private List<ECuentasCorrientes> GetCuentasCorrientes(EnumTipoPersona per)
        {
            NpgsqlDataReader dr = null;
            List<ECuentasCorrientes> ctacte = new List<ECuentasCorrientes>();
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryCuentasCorrientes(per));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            ctacte.Add(new ECuentasCorrientes(dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Cuentas Corrientes"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            return ctacte;
        }

        private List<EContacto> GetContactos(EnumTipoPersona per)
        {
            NpgsqlDataReader dr = null;
            List<EContacto> contacto = new List<EContacto>();
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryContactos(per));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            contacto.Add(new EContacto(dr,false));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Contactos"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            return contacto;
        }
        
        private List<EPlanilla> GetPlanilla()
        {
            NpgsqlDataReader dr = null;
            List<EPlanilla> plan = new List<EPlanilla>();
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, "select * from planillas.tb_planilla;");
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            plan.Add(new EPlanilla(dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Planilla"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            return plan ;
        }

        #endregion

        #region Metodos Privados

        private void GetDireccionesClientes(List <IEPersona> info)
        {
            List<EDireccion> direcciones = this.GetAddress(EnumTipoPersona.Cliente);
           
            if (direcciones.Count > 0)
            {
                foreach (IEPersona c in info)
                {
                    List<EDireccion> address = direcciones.FindAll(delegate(EDireccion dir)
                    {
                        return dir.IdPersona == c.IdPersona;
                    });
                    if (address != null)
                    {
                        c.AddAddressInfo(address);
                    }
                }
            }
        }

        private void GetDireccionesProveedores(List<IEPersona> info)
        {
            List<EDireccion> direcciones = this.GetAddress(EnumTipoPersona.Proveedor);
            if (direcciones.Count > 0)
            {
                foreach (IEPersona c in info)
                {
                    List<EDireccion> address = direcciones.FindAll(delegate(EDireccion dir)
                    {
                        return dir.IdPersona == c.IdPersona;
                    });
                    if (address != null)
                    {
                        c.AddAddressInfo(address);
                    }
                }
            }
        }

        private void GetDireccionesEmpleados(List<IEPersona> info)
        {
            List<EDireccion> direcciones = this.GetAddress(EnumTipoPersona.Empleado);

            if (direcciones.Count > 0)
            {
                foreach (IEPersona c in info)
                {
                    List<EDireccion> address = direcciones.FindAll(delegate(EDireccion dir)
                    {
                        return dir.IdPersona == c.IdPersona;
                    });
                    if (address != null)
                    {
                        c.AddAddressInfo(address);
                    }
                }
            }
        }

        private void GetCuentaCorrienteEmpleados(List<IEPersona> info)
        {
            List<ECuentasCorrientes> cuentas = this.GetCuentasCorrientes(EnumTipoPersona.Empleado);
            if (cuentas != null)
            {
                if (cuentas.Count > 0)
                {
                    foreach (IEPersona emp in info)
                    {
                        List<ECuentasCorrientes> cta = cuentas.FindAll(delegate(ECuentasCorrientes cc)
                        {
                            return cc.IdPersona == emp.IdPersona;
                        });
                        if (cta != null)
                        {
                            emp.AddAccountInfo(cta);
                        }
                    }
                }
            }
        }

        private void GetCuentaCorrienteProveedores(List<IEPersona> info)
        {
            List<ECuentasCorrientes> cuentas = this.GetCuentasCorrientes(EnumTipoPersona.Proveedor);
            if (cuentas != null)
            {
                if (cuentas.Count > 0)
                {
                    foreach (IEPersona pro in info)
                    {
                        List<ECuentasCorrientes> cta = cuentas.FindAll(delegate(ECuentasCorrientes cc)
                        {
                            return cc.IdPersona == pro.IdPersona;
                        });
                        if (cta != null)
                        {
                            pro.AddAccountInfo(cta);
                        }
                    }
                }
            }
        }

        private void GetContactosClientes(List<IEPersona> info)
        {
            List<EContacto> contactos = this.GetContactos(EnumTipoPersona.Cliente);

            if (contactos.Count > 0)
            {
                foreach (IEPersona c in info)
                {
                    List<EContacto> contact = contactos.FindAll(delegate(EContacto dir)
                    {
                        return dir.IdPersona == c.IdPersona;
                    });
                    if (contact != null)
                    {
                        c.AddContactInfo(contact);
                    }
                }
            }
        }

        private void GetContactosProveedores(List<IEPersona> info)
        {
            List<EContacto> contactos = this.GetContactos(EnumTipoPersona.Proveedor);

            if (contactos.Count > 0)
            {
                foreach (IEPersona c in info)
                {
                    List<EContacto> contact = contactos.FindAll(delegate(EContacto dir)
                    {
                        return dir.IdPersona == c.IdPersona;
                    });
                    if (contact != null)
                    {
                        c.AddContactInfo(contact);
                    }
                }
            }
        }

        private void GetPlanilla(List <IEPersona> info)
        {
            List<EPlanilla> plan = this.GetPlanilla();

            if (plan.Count > 0)
            {
                foreach (IEPersona emp in info)
                {
                    EPlanilla p = plan.Find(delegate(EPlanilla ep)
                    {
                        return ep.IdPersona == emp.IdPersona;
                    });
                    if (p != null)
                    {
                        emp.Planilla = p;
                    }
                }
            }
        }

        #endregion

        #region Funciones  Publicos    
        public List<EContacto> GetContactos(string patern)
        {
            NpgsqlDataReader dr = null;
            List<EContacto> contacto = new List<EContacto>();
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, string.Format("select * from planillas.tb_contactos {0}", patern));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            contacto.Add(new EContacto(dr, true));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Contactos"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            return contacto;
        }

        public List<IEPersona> GetClientes(int limit)
        {
            List<IEPersona> c = new List<IEPersona>();

            NpgsqlDataReader dr = null;
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryPersona(EnumTipoPersona.Cliente, limit, ""));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            c.Add( ObjectFactoryPersona.CreateClient (dr)); 
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Clientes"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            if (c.Count > 0)
            {
                this.GetDireccionesClientes(c);
                this.GetContactosClientes(c);
            }
            return c;
        }

        public List<IEPersona> GetClientes(int limit, string condicion)
        {
            List<IEPersona> c = new List<IEPersona>();

            NpgsqlDataReader dr = null;
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryPersona(EnumTipoPersona.Cliente, limit, condicion));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            c.Add( ObjectFactoryPersona.CreateClient(dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Clientes"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            if (c.Count > 0)
            {
                this.GetDireccionesClientes(c);
                this.GetContactosClientes(c);
            }
            return c;
        }

        public List<IEPersona> GetEmpleados(int limit)
        {
            List<IEPersona> c = new List<IEPersona>();
            
            NpgsqlDataReader dr = null;
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryPersona(EnumTipoPersona.Empleado, limit, ""));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            c.Add(ObjectFactoryPersona.CreateEmployee (dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Empleado"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            if (c.Count > 0)
            {
                this.GetDireccionesEmpleados(c);
                this.GetCuentaCorrienteEmpleados(c);
                this.GetPlanilla(c);
            }
            return c;
        }

        public List<IEPersona> GetProveedores(int limit)
        {
            List<IEPersona> c = new List<IEPersona>();
            NpgsqlDataReader dr = null;
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryPersona(EnumTipoPersona.Proveedor, limit, ""));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            c.Add(ObjectFactoryPersona.CreateSupplier (dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Proveedores"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            if (c.Count > 0)
            {
                this.GetDireccionesProveedores(c);
                this.GetCuentaCorrienteProveedores(c);
                this.GetContactosProveedores(c);
            }
            return c;
        }

        public List<IEPersona> GetProveedores(int limit, string condition)
        {
            List<IEPersona> c = new List<IEPersona>();
            NpgsqlDataReader dr = null;
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, this.GetQueryPersona(EnumTipoPersona.Proveedor, limit, condition));
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            c.Add(ObjectFactoryPersona.CreateSupplier (dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Proveedores"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            if (c.Count > 0)
            {
                this.GetDireccionesProveedores(c);
                this.GetCuentaCorrienteProveedores(c);
                this.GetContactosProveedores(c);
            }
            return c;
        }

        public List<ETipoCuentaCorriente> GetTipoCuentaCorriente()
        {
            List<ETipoCuentaCorriente> t = new List<ETipoCuentaCorriente>();
            NpgsqlDataReader dr = null;
            try
            {
                dr = PostgreSqlHelper.ExecuteReader(this.pCon, CommandType.Text, "select * from planillas.tb_tipoctacte;");
                if (dr != null)
                {
                    if (dr.HasRows)
                    {
                        while (dr.Read())
                        {
                            t.Add(new ETipoCuentaCorriente(dr));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Tipos de Cuentas Corrientes"), ex);
            }
            finally
            {
                DataBaseUtils.CloseNPgsqlDataReader(dr);
            }
            return t;
        }

        public DataTable GetListaClientes(ESistema obj)
        {
            DataTable dtb;
            NpgsqlConnection con = null;

            AccesoBD db = new AccesoBD();
            try
            {
                con = this.CurrentConection.GetPostgreSqlConnection();
                dtb = db.EjecutaModelView("planillas.tb_persona", new object[] { obj.Condicion }, con);
            }
            catch (NpgsqlException ex)
            {
                this.CurrentConection.CloseConnection(con);
                Console.Write(string.Format("{0}/{1}", ex.Message, ex.Source));
                DataBaseUtils.PrintMessajeError(this.mensajeExecuteReader.Replace("#replace", " Los Productos"), ex);
                return null;
            }
            finally
            {
                this.CurrentConection.CloseConnection(con);
            }
            return dtb;
        }

        #endregion

        #region Metodos de Mantenimiento

        public string SaveCliente(IEPersona c, EnumOperaciones op)
        {
            string msg = ""; 
            try
            {
                msg = (string)PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimientopersona", c.ToObject((int)op, EnumTipoPersona .Cliente));
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
            return msg;
        }

        public string SaveProveedor(IEPersona prov, EnumOperaciones op)
        {
            string msg = "";
            try
            {
                msg = (string)PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimientopersona", prov.ToObject((int)op, EnumTipoPersona.Proveedor));
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
            return msg;
        }

        public string SaveEmpleado(IEPersona emp, EnumOperaciones op)
        {
            string msg = "";
            try
            {
                msg = (string)PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimientopersona", emp.ToObject((int)op, EnumTipoPersona .Empleado));
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
            return msg;
        }

        public int SaveAddress(EDireccion address, EnumOperaciones op)
        {
            object res = PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimiento_direccion", address.ToObject((int)op));
            if (res == null)
            {
                return 0;
            }
            else
            {
                return Convert.ToInt32(res);
            }
        }

        public int SaveAcount(ECuentasCorrientes cte, EnumOperaciones op)
        {
            object res = PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimientocuentas", cte.ToObject((int)op));
            if (res == null)
            {
                return 0;
            }
            else
            {
                return Convert.ToInt32(res);
            }
        }

        public int SavePlanilla(EPlanilla plan)
        {
            object res = PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimientoplanilla", plan.ToObject());
            if (res == null) 
            {
                return 0;
            }
            else
            {
                return Convert.ToInt32(res.ToString());
            }
        }

        public int SaveContact(EContacto c, EnumOperaciones op)
        {
            object res = PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimiento_contactos", c.ContactToObject((int)op));
            if (res == null)
            {
                return -1;
            }
            else
            {
                return Convert.ToInt32(res.ToString());
            }
        }

        public int SaveContactRelation(EContacto c, EnumOperaciones op)
        {
            object res = PostgreSqlHelper.ExecuteScalar(this.pCon, "planillas.usp_mantenimiento_persona_contacto", c.ContactRelationToObject((int)op));
            if (res == null)
            {
                return -1;
            }
            else
            {
                return Convert.ToInt32(res.ToString());
            }
        }
        #endregion
    }
}